//
//  ProtocolBaseDataSecurity.m
//  Etion
//
//  Created by  user on 11-6-22.
//  Copyright 2011 GuangZhouXuanWu. All rights reserved.
//

#import "ProtocolBaseDataSecurity.h"

#import "CommandIDs.h"

#import "ProtocolStream.h"

#import "DataSecurity.h"

#define PROTOLVERSIONERROR	255

@implementation CProtocolBase(ProtocolBaseDataSecurity) 

-(int)IsNeedEncodeCompressProtocol:(int)nProtocolid
{
	int nResult=FALSE;
	switch(nProtocolid)
	{
		case ID_BUSINESSMESSAGEMANAGERSERVICE_GETDATASOURCE:
		{
			int n=0;
			if(nil!=[CDataSecurity GetCertificate].m_pubcer)
			{
				n+=(0==[CDataSecurity GetCertificate].m_pubcer.m_nTrans_compress?0:1);
				n+=(0==[CDataSecurity GetCertificate].m_pubcer.m_nTrans_DES?0:2);
			}
			else
				n=PROTOLVERSIONERROR;
			nResult=n;
			break;
		}
		default:
		{
			nResult=NO;
			break;
		}
	}
	return nResult;
}

-(void)WriteEnterprisenumber:(CProtocolStream*)ps
{
	[ps WriteInt:[CContext GetContext].m_nEnterprisenumber];
}

-(void)WriteUsernumber:(CProtocolStream*)ps
{
	[ps WriteInt:[CContext GetContext].m_nUsernumber];
}

-(NSData*)WriteProtocolStreamEncodeCompress:(CProtocolStream*)ps
{
	if(m_btVersion==PROTOLVERSIONERROR)
	{
		m_btVersion=0;
		return nil;
	}
	CProtocolStream* encodecompress=[[CProtocolStream new]autorelease];
	CProtocolStream* compress=[CProtocolStream new];
	[compress WriteShort:[CDataSecurity GetCertificate].m_pubcer.m_nTrans_compress];
	if(1==[CDataSecurity GetCertificate].m_pubcer.m_nTrans_compress)
	{
		unsigned char* dest=NULL;
		long unsigned int destlen=0;
		[[CDataSecurity GetDataSecurity].m_lzma LzmamemoryCompress:[[ps GetData]bytes] sourcelen:[[ps GetData]length] dest:&dest destlen:&destlen];
		if(destlen>0)
		{
			[compress WriteData:[NSData dataWithBytes:dest length:destlen]];
		}
		if(dest!=NULL)
			free(dest);
	}
	else
	{
		[compress WriteData:[ps GetData]];
	}
	if(0!=[CDataSecurity GetCertificate].m_pubcer.m_nTrans_DES)
	{
		char* ecdsach=NULL;
		unsigned int ecdsalen=0;
		char* eciesch=NULL;
		unsigned int ecieslen=0;
		char* hashch=NULL;
		unsigned int hashlen=0;
		char* aesch=NULL;
		unsigned int aeslen=0;
		const char* srcch=[[compress GetData] bytes];
		unsigned int srclen=[[compress GetData] length];
		[[CDataSecurity GetDataSecurity].m_crypto HashDump:srcch srclen:srclen dest:&hashch destlen:&hashlen];
		if(2==[CDataSecurity GetCertificate].m_pubcer.m_nTrans_DES)
			[[CDataSecurity GetDataSecurity].m_crypto AES_Encode:hashch keylen:hashlen src:srcch srclen:srclen dest:&aesch destlen:&aeslen];
		if(0!=[CDataSecurity GetCertificate].m_pubcer.m_nTrans_RSA)
		{
			if(2==[CDataSecurity GetCertificate].m_pubcer.m_nTrans_RSA)
				[[CDataSecurity GetDataSecurity].m_crypto ECIES_encrypt:[[CDataSecurity GetCertificate].m_pubcer.m_content bytes] publickeylen:[[CDataSecurity GetCertificate].m_pubcer.m_content length] source:hashch sourcelen:hashlen dest:&eciesch destlen:&ecieslen];
		}
		if(0!=[CDataSecurity GetCertificate].m_pubcer.m_nTrans_sign)
		{
			if(2==[CDataSecurity GetCertificate].m_pubcer.m_nTrans_sign)
			{
				if(nil==[CDataSecurity GetDataSecurity].m_pricercontent)
					[[CDataSecurity GetDataSecurity] ShowCerPswVerityView];
				[[CDataSecurity GetDataSecurity].m_crypto ECDSA_signer:[[CDataSecurity GetDataSecurity].m_pricercontent bytes] privatekeylen:[[CDataSecurity GetDataSecurity].m_pricercontent length] source:hashch sourcelen:hashlen signature:&ecdsach signaturelen:&ecdsalen];
			}
		}
		
		[encodecompress WriteShort:[CDataSecurity GetCertificate].m_pubcer.m_nTrans_hash*1000+[CDataSecurity GetCertificate].m_pubcer.m_nTrans_sign*100+
		 [CDataSecurity GetCertificate].m_pubcer.m_nTrans_RSA*10+[CDataSecurity GetCertificate].m_pubcer.m_nTrans_DES];
	
		if(eciesch!=NULL)
		{
			[encodecompress WriteData:[NSData dataWithBytes:eciesch length:ecieslen]];
			free(eciesch);
			eciesch=NULL;
		}
		if(ecdsach!=NULL)
		{
			[encodecompress WriteData:[NSData dataWithBytes:ecdsach length:ecdsalen]];
			free(ecdsach);
			ecdsach=NULL;
		}
		if(aesch!=NULL)
		{
			[encodecompress WriteData:[NSData dataWithBytes:aesch length:aeslen]];
			free(aesch);
			aesch=NULL;
		}
		if(hashch!=NULL)
		{
			free(hashch);
			hashch=NULL;
		}
	}
	else
		[encodecompress WriteData:[compress GetData]];
	
	[compress release];
	
	return 	[encodecompress GetData];
}

-(CProtocolStream*)ReadProtocolStreamEncodeCompress:(CProtocolStream*)ps
{
	int nResult=FALSE;
	
	CProtocolStream* result=[[CProtocolStream new]autorelease];

	int nLen=[ps ReadInt];
	nLen;
	
	int nTrans=[ps ReadShort];
	
	int nTrans_hash=nTrans/1000%10;
	nTrans_hash;
	int nTrans_sign=nTrans/100%10;
	nTrans_sign;
	int nTrans_RSA=nTrans/10%10;
	int nTrans_DES=nTrans%10;
	
//	int ecieslen=[ps ReadInt];
//	char* eciesch=NULL;
	
	NSData* ecies=[ps ReadData];
	NSData* ecdsa=[ps ReadData];
	ecdsa;
	NSData* aes=[ps ReadData];
	
	unsigned int ecdsalen=0;
	char* ecdsach=NULL;
	
//	unsigned int signaturelen=0;
//	char* signaturech=NULL;
//	int signatureresult=0;
	
	unsigned int aeslen=0;
	char* aesch=NULL;
	
	unsigned char* compressch=NULL;
	long unsigned int compresslen=0;
	
	if(0!=nTrans_DES)
	{
		if(2==nTrans_RSA)
		{
			if(nil==[CDataSecurity GetDataSecurity].m_pricercontent)
				nResult=[[CDataSecurity GetDataSecurity] ShowCerPswVerityView];
			else
				nResult=YES;
			if(YES==nResult)
				[[CDataSecurity GetDataSecurity].m_crypto ECIES_decrypt:[[CDataSecurity GetDataSecurity].m_pricercontent bytes] privatekeylen:[[CDataSecurity GetDataSecurity].m_pricercontent length] source:[ecies bytes] sourcelen:[ecies length] dest:&ecdsach destlen:&ecdsalen];
			if(ecdsach!=NULL)
				nResult=YES;
			else
				nResult=FALSE;
		}
		else
			nResult=YES;
	//	[[CLogicHelp GetDataSecurity].m_crypto ECDSA_verifying:[[CContext GetContext].m_pubcer.m_content bytes] publickeylen:[[CContext GetContext].m_pubcer.m_content length] source:[ecdsa bytes] sourcelen:[ecdsa length] signature:[ecies bytes] signaturelen:[ecies length] result:&signatureresult];
		
		if(YES==nResult&&2==nTrans_DES)
			[[CDataSecurity GetDataSecurity].m_crypto AES_Decode:ecdsach keylen:ecdsalen src:[aes bytes] srclen:[aes length] dest:&aesch destlen:&aeslen];
		if(aesch!=NULL)
			nResult=YES;
		else
			nResult=FALSE;
	}
	else
		nResult=YES;
	
	if(YES==nResult&&aesch!=NULL)
	{
		CProtocolStream* compressps=[CProtocolStream new];
		[[compressps GetData] appendData:[NSData dataWithBytes:aesch length:aeslen]];
		
		int nTrans_compress=[compressps ReadShort];
		
		if(0!=nTrans_compress)
		{
			NSData* compress=[compressps ReadData];
			
			if(1==nTrans_compress)
				[[CDataSecurity GetDataSecurity].m_lzma LzmamemoryDeCompress:[compress bytes] sourcelen:[compress length] dest:&compressch destlen:&compresslen];
			
			[[result GetData] appendData:[NSData dataWithBytes:compressch length:compresslen]];
		}
		else
		{
			[[result GetData] appendData:[compressps ReadData]];
		}
		[compressps release];
	}
	
	if(NULL!=ecdsach)
		free(ecdsach);
	
	if(NULL!=aesch)
		free(aesch);
	
	if(NULL!=compressch)
		free(compressch);
	
	return YES==nResult?result:nil;
}

+(CProtocolStream*)ReadProtocolDataEncodeCompress:(NSData*)data
{
	CProtocolBase* pb=[[CProtocolBase new]autorelease];
	CProtocolStream* ps=[[CProtocolStream new]autorelease];
	[[ps GetData] appendData:data];
	return [pb ReadProtocolStreamEncodeCompress:ps];
}

@end
